package com.sxl.ocr.ocronnx.handler;

import com.sxl.ocr.ocronnx.exception.OCRException;
import com.sxl.ocr.ocronnx.model.R;
import com.sxl.ocr.ocronnx.service.OCRService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.FormFieldPart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import java.io.File;
import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;

import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.ServerResponse.ok;

/**
 * description:
 * author: shenxiaolong
 * date: 2021/1/27  15:20
 */
@Slf4j
@Service
public class OCRHandler {

    @Autowired
    private OCRService ocrService;

    @Value("${ocr.tmpDir}")
    private String tmpDir;

    private static final String IMG_RESIZE = "imgResize";
    private static final String FILE = "file";


    @NotNull
    public Mono<ServerResponse> getOnnxOcrResult(ServerRequest request) {
        MultipartData param = new MultipartData();
        return request
                .multipartData()
                .map(MultiValueMap::toSingleValueMap)
                .map(partMap -> mapStructParam(partMap, param))
                .flatMap(filePart -> filePart.transferTo(param.filePath))
                .then(Mono.just(param))
                .flatMap(multiData -> Mono.just(R.success(ocrService.getOnnxOcrResult(multiData.filePath, multiData.imgResize))))
                .flatMap(result -> ok().contentType(APPLICATION_JSON).bodyValue(result))
                .onErrorResume(e -> Mono.just(R.fail(1001, "Error: " + e.getMessage()))
                        .flatMap(r -> ServerResponse.ok().contentType(APPLICATION_JSON).bodyValue(r)));

    }

    private FilePart mapStructParam(Map<String, Part> partMap, MultipartData param) {

        FormFieldPart imgResize = (FormFieldPart) partMap.get(IMG_RESIZE);
        FilePart filePart = (FilePart) partMap.get(FILE);

        Optional.ofNullable(imgResize).orElseThrow(() -> new OCRException(1003, IMG_RESIZE + "字段不能为空"));
        Optional.ofNullable(filePart).orElseThrow(() -> new OCRException(1003, FILE + "字段不能为空"));

        String filename = filePart.filename();
        Assert.hasText(filename, "文件名不能为空");
        String value = imgResize.value();

        File file = new File(tmpDir + filename);

        param.setFilePath(file.toPath());
        param.setImgResize(Integer.parseInt("".equals(value) ? "0" : value));
        return filePart;
    }

    @NotNull
    public Mono<ServerResponse> testHealth(ServerRequest request) {
        return ok()
                .contentType(APPLICATION_JSON)
                .bodyValue(R.success());
    }

    @Data
    private static class MultipartData {
        private Integer imgResize;
        private Path filePath;
    }
}